//
//  CoreDataManager.m
//  InterventixApp
//
//  Created by Diego Falcinelli on 23/06/13.
//
//

#import "CoreDataManager.h"
#import "ClienteCD.h"
#import "InterventoCD.h"
#import "ComunicationsUtils.h"
#import "DateUtil.h"
#import "NSData+Conversion.h"


@implementation CoreDataManager

- (id)init {
    self = [super init];
    if (self) {
        self.operationQueue = [NSOperationQueue new];
    }
    return self;
}
- (id)initWhidUserLogged:(UtenteCD *)userLogged {
    self = [super init];
    if (self) {
        self.operationQueue = [NSOperationQueue new];
        self.id_user_logged = userLogged.idutente;
        self.interventi_del_id = nil;
        self.interventi_mod = nil;
        self.interventi_status_id = nil;
        self.clienti_del_id = nil;
        self.clienti_mod = nil;
        self.utenti_del_id = nil;
        self.utenti_mod = nil;
        self.inuse_interventi = FALSE;
    }
    return self;
}
- (id)initWhidIdUserLogged:(NSNumber *)idUserLogged {
    self = [super init];
    if (self) {
        self.operationQueue = [NSOperationQueue new];
        self.operationQueue.maxConcurrentOperationCount = 1;
        self.id_user_logged = idUserLogged;
        self.interventi_del_id = nil;
        self.interventi_mod = nil;
        self.interventi_status_id = nil;
        self.clienti_del_id = nil;
        self.clienti_mod = nil;
        self.utenti_del_id = nil;
        self.utenti_mod = nil;
        self.inuse_interventi = FALSE;
    }
    return self;
}


#pragma mark -
#pragma mark Clienti

-(void) syncroClientiMT{
    @try{
        //Ciclo sui clienti da modificare
        for(NSDictionary *diz in self.clienti_mod){
            NSNumber *idCliente = [NSNumber numberWithInt:[[diz objectForKey:@"idcliente"] intValue]];
            ClienteCD *c = [self findCliente:idCliente];
            if(c==nil){
                [self addCliente:diz];
            }else{
                if([c.buffer isEqual: @0] && [c.inuse isEqual:@0]){
                    [self modCliente:diz];
                }
            }
            //NSLog(@"Mod Cliente: %@", idCliente);
        }
        
        
        //Ciclo sui clienti da eliminare
        for(NSString *idcliente in self.clienti_del_id){
            [self delCliente:[NSNumber numberWithInt:[idcliente intValue]]];
            //NSLog(@"Del Cliente: %@", idcliente);
        }
        
        self.clienti_mod = nil;
        self.clienti_del_id = nil;
        self.inuse_clienti = FALSE;
    }@catch (NSException *ex) {
        NSLog(@"%@",ex);
    }
}
-(void) syncroClienti:(NSArray *) clienti_MOD del: (NSArray *) clienti_DEL{
    
    //Setto gli array che vengo dalla richiesta JSON
    if(self.inuse_clienti == FALSE){
        self.inuse_clienti = TRUE;
        self.clienti_del_id = clienti_DEL;
        self.clienti_mod = clienti_MOD;
        
        //Creo l'operazione MultiThread e la lancio
        //NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(syncroClientiMT) object:nil];
        
        //Aggiungo L'operazione nella Coda
        //[self.operationQueue addOperation:operation];
        
        NSOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(syncroClientiMT) object:nil];
        [operation start];
    }
}
-(ClienteCD *)findCliente:(NSNumber *) idcliente{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Otteniamo il puntatore al NSManagedContext"];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza"];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"ClienteCD" inManagedObjectContext:context];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(idcliente = %@) AND (user = %d)", idcliente, [self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return (ClienteCD*)fo[0];
}
-(void) addCliente:(NSDictionary *) clienteDiz{
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    ClienteCD *cliente = [NSEntityDescription
                          insertNewObjectForEntityForName:@"ClienteCD"
                          inManagedObjectContext:context];
    
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    cliente.idcliente      = [NSNumber numberWithInt:[[clienteDiz objectForKey:@"idcliente"] intValue]];
    cliente.nominativo     = ([clienteDiz objectForKey:@"nominativo"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"nominativo"];
    cliente.codice_fiscale = ([clienteDiz objectForKey:@"codicefiscale"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"codicefiscale"];
    cliente.partita_iva    = ([clienteDiz objectForKey:@"partitaiva"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"partitaiva"];
    cliente.fax            = ([clienteDiz objectForKey:@"fax"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"fax"];
    cliente.email          = ([clienteDiz objectForKey:@"email"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"email"];
    cliente.referente      = ([clienteDiz objectForKey:@"referente"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"referente"];
    cliente.citta          = ([clienteDiz objectForKey:@"citta"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"citta"];
    cliente.indirizzo      = ([clienteDiz objectForKey:@"indirizzo"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"indirizzo"];
    cliente.interno        = ([clienteDiz objectForKey:@"interno"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"interno"];
    cliente.ufficio        = ([clienteDiz objectForKey:@"ufficio"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"ufficio"];
    cliente.note           = ([clienteDiz objectForKey:@"note"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"note"];
    cliente.revisione      = [NSNumber numberWithInt:[[clienteDiz objectForKey:@"revisione"] intValue]];
    cliente.user = self.id_user_logged;
    
    if([[clienteDiz objectForKey:@"cancellato"] boolValue] == true){
        cliente.cancellato = @1;
    }else{
        cliente.cancellato = @0;
    }
    if([[clienteDiz objectForKey:@"cestinato"] boolValue] == true){
        cliente.cestinato = @1;
    }else{
        cliente.cestinato = @0;
    }
    // Buffer di default FALSE;
    cliente.buffer = @0;
    cliente.inuse = @0;
    
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
}
-(void) modCliente:(NSDictionary *) clienteDiz{
    
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità  che ci interessa
    ClienteCD *cliente = [self findCliente:[NSNumber numberWithInt:[[clienteDiz objectForKey:@"idcliente"] intValue]]];
    
    
    //Usando il Key-Value Coding inseriamo i dati presi dal JSON nell'istanza dell'Entità appena creata
    cliente.idcliente      = [NSNumber numberWithInt:[[clienteDiz objectForKey:@"idcliente"] intValue]];
    cliente.nominativo     = ([clienteDiz objectForKey:@"nominativo"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"nominativo"];
    cliente.codice_fiscale = ([clienteDiz objectForKey:@"codicefiscale"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"codicefiscale"];
    cliente.partita_iva    = ([clienteDiz objectForKey:@"partitaiva"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"partitaiva"];
    cliente.fax            = ([clienteDiz objectForKey:@"fax"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"fax"];
    cliente.email          = ([clienteDiz objectForKey:@"email"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"email"];
    cliente.referente      = ([clienteDiz objectForKey:@"referente"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"referente"];
    cliente.citta          = ([clienteDiz objectForKey:@"citta"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"citta"];
    cliente.indirizzo      = ([clienteDiz objectForKey:@"indirizzo"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"indirizzo"];
    cliente.interno        = ([clienteDiz objectForKey:@"interno"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"interno"];
    cliente.ufficio        = ([clienteDiz objectForKey:@"ufficio"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"ufficio"];
    cliente.note           = ([clienteDiz objectForKey:@"note"] == [NSNull null]) ? nil : [clienteDiz objectForKey:@"note"];
    cliente.revisione      = [NSNumber numberWithInt:[[clienteDiz objectForKey:@"revisione"] intValue]];
    cliente.user = self.id_user_logged;
    
    if([[clienteDiz objectForKey:@"cancellato"] boolValue] == true){
        cliente.cancellato = @1;
    }else{
        cliente.cancellato = @0;
    }
    if([[clienteDiz objectForKey:@"cestinato"] boolValue] == true){
        cliente.cestinato = @1;
    }else{
        cliente.cestinato = @0;
    }
    
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
}
-(void) delCliente:(NSNumber *) idcliente{
    //Cerco l'istanza da eliminare
    ClienteCD *cliente = [self findCliente:idcliente];
    
    //Controllo l'esistenza del cliente nel DB
    if(cliente!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        //Segnalo il contesto l'istanza da eliminare
        [context deleteObject:cliente];
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        }
    }
}
-(void) delClienteObject:(ClienteCD *) cliente{
    //Controllo l'esistenza del cliente nel DB
    if(cliente!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        //Segnalo il contesto l'istanza da eliminare
        [context deleteObject:cliente];
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il delete: %@", [error localizedDescription]);
        }
    }
}


-(NSArray *)getClienti{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"ClienteCD" inManagedObjectContext:context];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(user = %d)",[self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"nominativo" ascending:YES];
    //Return dell entita con il casting
    NSArray *results = [fo sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
    return results;
    
}
-(NSArray *) likeClienti:(NSString *)like{
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Otteniamo il puntatore al NSManagedContext"];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza"];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"ClienteCD" inManagedObjectContext:context];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(nominativo contains[cd] %@) AND (user = %d)", like,[self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    //sort
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"nominativo" ascending:YES];
    //Return dell entita con il casting
    NSArray *results = [fo sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
    return results;
}

+(unsigned long long) hashcodeCliente:(ClienteCD *) i{
    unsigned long long h = [i.idcliente hash];
    h+= [i.nominativo hash];
    h+= [i.codice_fiscale hash];
    h+= [i.partita_iva hash];
    h+= [i.fax hash];
    h+= [i.telefono hash];
    h+= [i.email hash];
    h+= [i.referente hash];
    h+= [i.citta hash];
    h+= [i.revisione hash] * 231;
    h+= [i.indirizzo hash];
    h+= [i.interno hash];
    h+= [i.ufficio hash];
    h+= [i.note hash];
    h+= [i.cancellato longLongValue] + [i.cestinato longLongValue];
    return h;
}

-(NSString *) calcStatusCliente:(ClienteCD *)client{
    @try{
        //NSLog(@"id : %d, buffer : %@",[client.idcliente intValue],client.buffer);
        if(client == nil) return @"NULL";
        if([client.idcliente intValue]>0 && [client.buffer isEqual:@0]) return @"SAVE";
        if([client.idcliente intValue]>0 && [client.buffer isEqual:@1]) return @"MOD";
        if([client.idcliente intValue]<0 && [client.buffer isEqual:@0]) return @"NEW";
        if([client.idcliente intValue]<0 && [client.buffer isEqual:@1]) return @"NEW";
        return @"NULL";
    }@catch (NSException *ex) {
        return @"EX";
    }
}




#pragma mark -
#pragma mark Utenti

-(void) syncroUtentiMT{
    @try{
        //Ciclo sui utenti da modificare
        for(NSDictionary *diz in self.utenti_mod){
            NSNumber *idutente = [NSNumber numberWithInt:[[diz objectForKey:@"idutente"] intValue]];
            UtenteCD *c = [self findUtente:idutente];
            
            if(c==nil){
                [self addUtente:diz];
            }else{
                [self modUtente:diz];
            }
            //NSLog(@"Mod utente: %@", idutente);
        }
        
        //Ciclo sui utenti da eliminare
        for(NSString *idutente in self.utenti_del_id){
            [self delUtente:[NSNumber numberWithInt:[idutente intValue]]];
            //NSLog(@"Del utente: %@", idutente);
        }
        self.utenti_mod = nil;
        self.utenti_del_id = nil;
        self.inuse_utenti = FALSE;
    }@catch (NSException *ex) {
        NSLog(@"%@",ex);
    }
    
}
-(void) syncroUtenti:(NSArray *) utenti_MOD del: (NSArray *) utenti_DEL{
    
    //Controllo sell'array è in uso
    if(self.inuse_utenti == FALSE){
        
        //Setto l'array in uso;
        self.inuse_utenti = TRUE;
        
        //Setto gli array che vengo dalla richiesta JSON
        self.utenti_mod = utenti_MOD;
        self.utenti_del_id = utenti_DEL;
        
        //Creo l'operazione MultiThread e la lancio
        //NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(syncroUtentiMT) object:nil];
        
        //Aggiungo L'operazione nella Coda
        //[self.operationQueue addOperation:operation];
        
        
        NSOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(syncroUtentiMT) object:nil];
        [operation start];
    }
}
-(UtenteCD *)findUtente:(NSNumber *) idutente{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"UtenteCD" inManagedObjectContext:context];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(idutente = %@) AND (user = %d)", idutente, [self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return (UtenteCD*)fo[0];
}
-(void) addUtente:(NSDictionary *) utenteDiz{
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    UtenteCD *utente = [NSEntityDescription
                        insertNewObjectForEntityForName:@"UtenteCD"
                        inManagedObjectContext:context];
    
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    utente.idutente      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"idutente"] intValue]];
    utente.nome          = ([utenteDiz objectForKey:@"nome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"nome"];
    utente.cognome       = ([utenteDiz objectForKey:@"cognome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"cognome"];
    utente.username      = ([utenteDiz objectForKey:@"username"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"username"];
    utente.password      = ([utenteDiz objectForKey:@"password"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"password"];
    utente.email         = ([utenteDiz objectForKey:@"email"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"email"];
    utente.tipo          = ([utenteDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"tipo"];
    utente.revisione      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"revisione"] intValue]];
    utente.user = self.id_user_logged;
    
    if([[utenteDiz objectForKey:@"cancellato"] boolValue] == true){
        utente.cancellato = @1;
    }else{
        utente.cancellato = @0;
    }
    if([[utenteDiz objectForKey:@"cestinato"] boolValue] == true){
        utente.cestinato = @1;
    }else{
        utente.cestinato = @0;
    }
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
}
-(void) modUtente:(NSDictionary *) utenteDiz{
    
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità  che ci interessa
    UtenteCD *utente = [self findUtente:[NSNumber numberWithInt:[[utenteDiz objectForKey:@"idutente"] intValue]]];
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    utente.idutente      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"idutente"] intValue]];
    utente.nome          = ([utenteDiz objectForKey:@"nome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"nome"];
    utente.cognome       = ([utenteDiz objectForKey:@"cognome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"cognome"];
    utente.username      = ([utenteDiz objectForKey:@"username"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"username"];
    utente.password      = ([utenteDiz objectForKey:@"password"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"password"];
    utente.email         = ([utenteDiz objectForKey:@"email"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"email"];
    utente.tipo          = ([utenteDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"tipo"];
    utente.revisione      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"revisione"] intValue]];
    utente.user = self.id_user_logged;
    if([[utenteDiz objectForKey:@"cancellato"] boolValue] == true){
        utente.cancellato = @1;
    }else{
        utente.cancellato = @0;
    }
    if([[utenteDiz objectForKey:@"cestinato"] boolValue] == true){
        utente.cestinato = @1;
    }else{
        utente.cestinato = @0;
    }
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
}
-(void) delUtente:(NSNumber *) idutente{
    //Cerco l'istanza da eliminare
    UtenteCD *utente  = [self findUtente:idutente];
    
    //Controllo l'esistenza del cliente nel DB
    if(utente!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        //Segnalo il contesto l'istanza da eliminare
        [context deleteObject:utente];
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        }
    }
}

-(NSArray *) getUtenti:(NSString *) tipo{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Otteniamo il puntatore al NSManagedContext"];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza"];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"UtenteCD" inManagedObjectContext:context];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(tipo = %@) AND (user = %d)", tipo,[self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return fo;
}

-(NSArray *) getUtentiAll{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Otteniamo il puntatore al NSManagedContext"];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza"];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"UtenteCD" inManagedObjectContext:context];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return fo;
}


+(UtenteCD *) createUtenteCDFromDictionary:(NSDictionary *) utenteDiz{
    
    CoreDataManager *core = [[CoreDataManager alloc]init];
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [core managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    UtenteCD *utente = [NSEntityDescription
                        insertNewObjectForEntityForName:@"UtenteCD"
                        inManagedObjectContext:context];
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    utente.idutente      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"idutente"] intValue]];
    utente.nome          = ([utenteDiz objectForKey:@"nome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"nome"];
    utente.cognome       = ([utenteDiz objectForKey:@"cognome"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"cognome"];
    utente.username      = ([utenteDiz objectForKey:@"username"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"username"];
    utente.password      = ([utenteDiz objectForKey:@"password"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"password"];
    utente.email         = ([utenteDiz objectForKey:@"email"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"email"];
    utente.tipo          = ([utenteDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [utenteDiz objectForKey:@"tipo"];
    utente.revisione      = [NSNumber numberWithInt:[[utenteDiz objectForKey:@"revisione"] intValue]];
    if([[utenteDiz objectForKey:@"cancellato"] boolValue] == true){
        utente.cancellato = @1;
    }else{
        utente.cancellato = @0;
    }
    if([[utenteDiz objectForKey:@"cestinato"] boolValue] == true){
        utente.cestinato = @1;
    }else{
        utente.cestinato = @0;
    }
    return utente;
}

+(unsigned long long) hashcodeUtente:(UtenteCD *) i{
    unsigned long long h = [i.idutente hash];
    h+= [i.nome hash];
    h+= [i.cognome hash];
    h+= [i.username hash];
    h+= [i.password hash];
    h+= [i.email hash];
    h+= [i.tipo hash];
    h+= [i.revisione hash] * 331;
    h+= [i.cancellato longLongValue] + [i.cestinato longLongValue];
    return llabs(h);
}


#pragma mark -
#pragma mark Interventi

-(void) syncroInterventiMT{
    @try{
        //Ciclo sui Interventi da modificare
        for(NSDictionary *diz in self.interventi_mod){
            NSNumber *idintervento = [NSNumber numberWithInt:[[diz objectForKey:@"idintervento"] intValue]];
            InterventoCD *c = [self findIntervento:idintervento];
          
            NSNumber *conflict = [NSNumber numberWithBool:[[diz objectForKey:@"conflitto"] boolValue]];
            if([conflict  isEqual: @0]){
                if(c==nil){
                    [self addIntervento:diz withBuffer:FALSE];
                }else{
                    if([c.buffer isEqual: @0] && [c.inuse isEqual:@0]){
                        [self modIntervento:diz withBuffer:FALSE];
                    }
                }
                //NSLog(@"Mod/Add intervento: %@", idintervento);
            }else{
                if(c==nil){
                    [self addIntervento:diz withBuffer:FALSE];
                }else{
                    c.conflitto = @1;
                    NSError *error;
                    if (![[self managedObjectContext] save:&error]) {
                        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
                        
                        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
                        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
                        if(detailedErrors != nil && [detailedErrors count] > 0) {
                            for(NSError* detailedError in detailedErrors) {
                                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
                            }
                        }
                        else {
                            NSLog(@"  %@", [error userInfo]);
                        }
                        
                    }
                }
            }
        }
        
        //Ciclo sui interventi cancellati
        for(NSString *idintervento in self.interventi_del_id){
            [self delIntervento:[NSNumber numberWithInt:[idintervento intValue]]];
            //NSLog(@"Del intervento: %@", idintervento);
        }
        
        
        
        //Ciclo sui interventi status di verifica
        for(InterventoCD *i in [self getInterventi]){
            //NSLog(@"Status: %@",i.idintervento);
            bool delete = true;
            for(NSString *idintervento in self.interventi_status_id){
                if([i.idintervento intValue] == [idintervento intValue]){
                    delete = false;
                    break;
                }
            }
            if(delete == true){[self delIntervento:i.idintervento];}
        }
        
        self.interventi_del_id = nil;
        self.interventi_mod = nil;
        self.interventi_status_id = nil;
        self.inuse_interventi = FALSE;
        //NSLog(@"interventi_mod: %d; interventi_del_id: %d; interventi_status_id: %d",self.interventi_mod.count,self.interventi_del_id.count,self.interventi_status_id.count);
        
    }@catch (NSException *ex) {
        NSLog(@"%@",ex);
    }
    
}
-(void) syncroInterventi:(NSArray *) intervento_MOD del: (NSArray *) intervento_DEL status:(NSArray *) status_ID{
    //NSLog(@"syncroInterventi");
    //Setto gli array che vengo dalla richiesta JSON
    if(self.inuse_interventi == FALSE){
        self.inuse_interventi = TRUE;
        self.interventi_mod = intervento_MOD;
        self.interventi_del_id = intervento_DEL;
        self.interventi_status_id = status_ID;
        
        NSOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(syncroInterventiMT) object:nil];
        [operation start];
    }
}
-(InterventoCD *)findIntervento:(NSNumber *)idintervento{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"InterventoCD" inManagedObjectContext:context];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(idintervento = %@) AND (user = %d)", idintervento,[self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return (InterventoCD*)fo[0];
}
-(void) addIntervento:(NSDictionary *)interDiz withBuffer:(BOOL)buffer{
    
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    InterventoCD *intervento = [NSEntityDescription insertNewObjectForEntityForName:@"InterventoCD" inManagedObjectContext:context];
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    intervento.idintervento      = [NSNumber numberWithInt:[[interDiz objectForKey:@"idintervento"] intValue]];
    intervento.modalita          = ([interDiz objectForKey:@"modalita"] == [NSNull null]) ? nil : [interDiz objectForKey:@"modalita"];
    intervento.motivo            = ([interDiz objectForKey:@"motivo"] == [NSNull null]) ? nil : [interDiz objectForKey:@"motivo"];
    intervento.nominativo        = ([interDiz objectForKey:@"nominativo"] == [NSNull null]) ? nil : [interDiz objectForKey:@"nominativo"];
    intervento.note              = ([interDiz objectForKey:@"note"] == [NSNull null]) ? nil : [interDiz objectForKey:@"note"];
    intervento.prodotto          = ([interDiz objectForKey:@"prodotto"] == [NSNull null]) ? nil : [interDiz objectForKey:@"prodotto"];
    intervento.rif_fattura       = ([interDiz objectForKey:@"riffattura"] == [NSNull null]) ? nil : [interDiz objectForKey:@"riffattura"];
    intervento.rif_scontrino     = ([interDiz objectForKey:@"rifscontrino"] == [NSNull null]) ? nil : [interDiz objectForKey:@"rifscontrino"];
    intervento.tipologia         = ([interDiz objectForKey:@"tipologia"] == [NSNull null]) ? nil : [interDiz objectForKey:@"tipologia"];
    intervento.revisione         = ([interDiz objectForKey:@"revisione"] == [NSNull null]) ? @0 : [NSNumber numberWithInt:[[interDiz objectForKey:@"revisione"] intValue]];
    intervento.costo_accessori   = ([interDiz objectForKey:@"costoaccessori"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"costoaccessori"] floatValue]] decimalValue]];
    
    intervento.costo_componenti  = ([interDiz objectForKey:@"costocomponenti"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"costocomponenti"] floatValue]] decimalValue]];
    
    intervento.costo_manodopera  = ([interDiz objectForKey:@"costomanodopera"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"costomanodopera"] floatValue]] decimalValue]];
    
    intervento.importo           = ([interDiz objectForKey:@"importo"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"importo"] floatValue]] decimalValue]];
    
    intervento.iva               = ([interDiz objectForKey:@"iva"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"iva"] floatValue]] decimalValue]];
    
    intervento.totale            = ([interDiz objectForKey:@"totale"] == [NSNull null]) ? [NSDecimalNumber decimalNumberWithString:@"0"] : [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithFloat:[[interDiz objectForKey:@"totale"] floatValue]] decimalValue]];
    
    
    intervento.dataora           = ([interDiz objectForKey:@"dataora"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[interDiz objectForKey:@"dataora"]];
    intervento.firma             = ([interDiz objectForKey:@"firma"] == [NSNull null]) ? nil :[NSData dataFromHexString:[interDiz objectForKey:@"firma"]];
    intervento.cancellato        = ([interDiz objectForKey:@"cancellato"] == [NSNull null]) ? nil :[NSNumber numberWithBool:[[interDiz objectForKey:@"cancellato"] boolValue]];
    intervento.cestinato         = ([interDiz objectForKey:@"cestinato"] == [NSNull null]) ? nil :[NSNumber numberWithBool:[[interDiz objectForKey:@"cancellato"] boolValue]];
    intervento.chiuso            = ([interDiz objectForKey:@"chiuso"] == [NSNull null]) ? nil :[NSNumber numberWithBool:[[interDiz objectForKey:@"chiuso"] boolValue]];
    intervento.conflitto         = ([interDiz objectForKey:@"conflitto"] == [NSNull null]) ? nil :[NSNumber numberWithBool:[[interDiz objectForKey:@"conflitto"] boolValue]];
    intervento.saldato           = ([interDiz objectForKey:@"saldato"] == [NSNull null]) ? nil :[NSNumber numberWithBool:[[interDiz objectForKey:@"saldato"] boolValue]];
    intervento.buffer            = @0;
    intervento.inuse             = @0;
    intervento.cliente           = [self findCliente:[NSNumber numberWithInt:[[interDiz objectForKey:@"cliente"] intValue]]];
    intervento.tecnico           = [self findUtente:[NSNumber numberWithInt:[[interDiz objectForKey:@"tecnico"] intValue]]];
    
    intervento.numero          = ([interDiz objectForKey:@"numero"] == [NSNull null]) ? @0 : [NSNumber numberWithInt:[[interDiz objectForKey:@"numero"] intValue]];
    
    intervento.user = self.id_user_logged;
    
    
    
    
    for(NSDictionary *dettaglioDiz in [interDiz objectForKey:@"dettagliintervento"]){
        DettaglioCD *dettaglio = [NSEntityDescription
                                  insertNewObjectForEntityForName:@"DettaglioCD"
                                  inManagedObjectContext:context];
        
        
        //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
        dettaglio.iddettaglio = [NSNumber numberWithInt:[[dettaglioDiz objectForKey:@"iddettagliointervento"] intValue]];
        dettaglio.descrizione = ([dettaglioDiz objectForKey:@"descrizione"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"descrizione"];
        dettaglio.tipo        = ([dettaglioDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"tipo"];
        dettaglio.oggetto     = ([dettaglioDiz objectForKey:@"oggetto"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"oggetto"];
        dettaglio.inizio      = ([dettaglioDiz objectForKey:@"inizio"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"inizio"]];
        dettaglio.fine        = ([dettaglioDiz objectForKey:@"fine"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"fine"]];
        
        [intervento addDettagliObject:dettaglio];
        
        //[self addDettaglio:dettaglioDiz];
        //[intervento addDettagliObject:[self findDettaglio:[NSNumber numberWithInt:[[dettaglioDiz objectForKey:@"iddettagliointervento"] intValue]]]];
    }
    
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        
        NSLog(@"Failed to save to data store: %@", [error localizedDescription]);
        NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
        if(detailedErrors != nil && [detailedErrors count] > 0) {
            for(NSError* detailedError in detailedErrors) {
                NSLog(@"  DetailedError: %@", [detailedError userInfo]);
            }
        }
        else {
            NSLog(@"  %@", [error userInfo]);
        }
        
    }
}
-(void) modIntervento:(NSDictionary *) interDiz withBuffer:(BOOL) buffer{
    //Otteniamo il puntatore al NSManagedContext
    //NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità  che ci interessa
    //InterventoCD *intervento = [self findIntervento:[NSNumber numberWithInt:[[interDiz objectForKey:@"idintervento"] longLongValue]]];
    
    [self delIntervento:[NSNumber numberWithLongLong:[[interDiz objectForKey:@"idintervento"] longLongValue]]];
    [self addIntervento:interDiz withBuffer:buffer];
    
    
}
-(void) delIntervento:(NSNumber *)idintervento{
    //Cerco l'istanza da eliminare
    InterventoCD *intervento  = [self findIntervento:idintervento];
    
    //Controllo l'esistenza del cliente nel DB
    if(intervento!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        //Segnalo il contesto l'istanza da eliminare
        [context deleteObject:intervento];
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        }
    }
}
-(NSArray *)getInterventi{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Otteniamo il puntatore al NSManagedContext"];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza"];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"InterventoCD" inManagedObjectContext:context];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(user = %d)", [self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return fo;
}
-(NSArray *)getInterventiToSend{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"InterventoCD" inManagedObjectContext:context];
	[fetchRequest setEntity:entity];
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"((buffer = 1) OR (idintervento < 0)) AND (user = %d)",[self.id_user_logged intValue]];
    [fetchRequest setPredicate:predicate];
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"idintervento" ascending:NO];
    //Return dell entita con il casting
    NSArray *results = [[fo filteredArrayUsingPredicate:predicate] sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
    return results;
}
+(unsigned long long) hashcodeIntervento:(InterventoCD *) i{
    unsigned long long h = ([i.saldato longLongValue] + [i.cancellato longLongValue] + [i.cestinato longLongValue] + [i.chiuso longLongValue] + [i.conflitto longLongValue])*33;
    h += [i.costo_accessori hash] + 881 + ([i.costo_accessori doubleValue] * 251);
    h += [i.costo_componenti hash]+ 479 + ([i.costo_componenti doubleValue] * 193);
    h += [i.costo_manodopera hash]+ 997 + ([i.costo_manodopera doubleValue] * 101);
    h += [i.iva hash] + 88;
    h += [i.importo hash]  + 99;
    h += [i.totale hash]+ 67;
    h += [i.tipologia hash];
    h += [i.modalita hash];
    h += [i.prodotto hash];
    h += [i.motivo hash];
    h += [i.nominativo hash];
    h += [i.note hash];
    h += [i.rif_fattura hash];
    h += [i.rif_scontrino hash];
    h += [i.revisione hash] + 21;
    h += [i.firma hash] + (long long)[i.firma.base64Encoding hash] ;
    h += [i.dataora hash]+111;
    
    h += [self hashcodeUtente:i.tecnico];
    h += [self hashcodeCliente:i.cliente];
    for(DettaglioCD *di in i.dettagli){
        h += [self hashcodeDettaglio:di];
    }
    
    unsigned long long hh = llabs(h);
    return hh;
}

-(NSString *) calcStatusIntervento:(InterventoCD *)inter{
    @try{
        if(inter == nil) return @"NULL";
        if([inter.idintervento intValue]>0 && [inter.buffer isEqual:@0]) return @"SAVE";
        if([inter.idintervento intValue]>0 && [inter.buffer isEqual:@1]) return @"MOD";
        if([inter.idintervento intValue]<0 && [inter.buffer isEqual:@0]) return @"NEW";
        if([inter.idintervento intValue]<0 && [inter.buffer isEqual:@1]) return @"NEW";
        return @"NULL";
    }@catch (NSException *ex) {
        return @"EX";
    }
}



#pragma mark -
#pragma mark Dettagli

-(DettaglioCD *)findDettaglio:(NSNumber *) iddettaglio{
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"DettaglioCD" inManagedObjectContext:context];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"istanziamo l'EntitÃ  da passare alla Fetch Request"];
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(iddettaglio = %@)", iddettaglio];
    [fetchRequest setPredicate:predicate];
	//[self performSelectorInBackground:@selector(toLog:) withObject:@"Fetch"];
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    //Return dell entita con il casting
    return (DettaglioCD*)fo[0];
}
-(void) addDettaglio:(NSDictionary *)dettaglioDiz{
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    DettaglioCD *dettaglio = [NSEntityDescription
                              insertNewObjectForEntityForName:@"DettaglioCD"
                              inManagedObjectContext:context];
    
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    dettaglio.iddettaglio = [NSNumber numberWithInt:[[dettaglioDiz objectForKey:@"iddettagliointervento"] intValue]];
    dettaglio.descrizione = ([dettaglioDiz objectForKey:@"descrizione"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"descrizione"];
    dettaglio.tipo        = ([dettaglioDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"tipo"];
    dettaglio.oggetto     = ([dettaglioDiz objectForKey:@"oggetto"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"oggetto"];
    dettaglio.inizio      = ([dettaglioDiz objectForKey:@"inizio"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"inizio"]];
    dettaglio.fine        = ([dettaglioDiz objectForKey:@"fine"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"fine"]];
    
    
    for (NSString *idtecnico in [dettaglioDiz objectForKey:@"tecniciintervento"]) {
        [dettaglio addTecniciObject:[self findUtente:[NSNumber numberWithInt:[idtecnico intValue]]]];
    }
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
}
-(void) modDettaglio:(NSDictionary *)dettaglioDiz{
    //Otteniamo il puntatore al NSManagedContext
    NSManagedObjectContext *context = [self managedObjectContext];
    
    //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
    DettaglioCD *dettaglio = [self findDettaglio:[NSNumber numberWithInt:[[dettaglioDiz objectForKey:@"iddettaglio"] intValue]]];
    
    
    //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'EntitÃ  appena creata
    dettaglio.descrizione = ([dettaglioDiz objectForKey:@"descrizione"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"descrizione"];
    dettaglio.tipo        = ([dettaglioDiz objectForKey:@"tipo"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"tipo"];
    dettaglio.oggetto     = ([dettaglioDiz objectForKey:@"oggetto"] == [NSNull null]) ? nil : [dettaglioDiz objectForKey:@"oggetto"];
    dettaglio.inizio      = ([dettaglioDiz objectForKey:@"inizio"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"inizio"]];
    dettaglio.fine        = ([dettaglioDiz objectForKey:@"fine"] == [NSNull null]) ? nil : [DateUtil LongNSStringToNSDate:[dettaglioDiz objectForKey:@"fine"]];
    
    for (NSString *idtecnico in [dettaglioDiz objectForKey:@"tecniciintervento"]) {
        [dettaglio addTecniciObject:[self findUtente:[NSNumber numberWithInt:[idtecnico intValue]]]];
    }
    
    //Effettuiamo il salvataggio gestendo eventuali errori
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
    }
    
}
-(void) delDettaglio:(NSNumber *)iddettaglio{
    //Cerco l'istanza da eliminare
    DettaglioCD *dett  = [self findDettaglio:iddettaglio];
    
    //Controllo l'esistenza del cliente nel DB
    if(dett!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        //Segnalo il contesto l'istanza da eliminare
        [context deleteObject:dett];
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        }
    }
}
+(unsigned long long) hashcodeDettaglio:(DettaglioCD *) i{
    unsigned long long h = [i.iddettaglio hash];
    h+= [i.tipo hash];
    h+= [i.oggetto hash];
    h+= [i.descrizione hash];
    h+= [i.inizio hash] *22;
    h+= [i.fine hash] * 132;
    for(NSNumber *n in i.tecnici){
        h+= [n hash] ;
    }
    h+= ([i.tecnici count]*33);
    return llabs(h);
}


-(void) saveDettaglio:(DettaglioCD*)dettaglio{
    //Controllo l'esistenza del cliente nel DB
    if(dettaglio!=nil){
        //Otteniamo il puntatore al NSManagedContext
        NSManagedObjectContext *context = [self managedObjectContext];
        
        
        //Effettuiamo il salvataggio gestendo eventuali errori
        NSError *error;
        if (![context save:&error]) {
            NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
        }
    }
}

-(BOOL) checkDettaglio:(DettaglioCD*)dettaglio{
    
    if([dettaglio.oggetto isEqual:[NSNull null]] || dettaglio.oggetto == nil || [dettaglio.oggetto isEqualToString:@""] ||
       dettaglio.tipo == nil    || [dettaglio.tipo isEqual:[NSNull null]]   ||
       dettaglio.inizio == nil  || [dettaglio.inizio isEqual:[NSNull null]] ||
       dettaglio.fine == nil    || [dettaglio.fine isEqual:[NSNull null]]
       ){
        return false;
    }
    return true;
}

-(BOOL) checkCliente:(ClienteCD*)cliente{
    if([cliente.nominativo isEqual:[NSNull null]] || cliente.nominativo == nil || [cliente.nominativo isEqualToString:@""] ||
       [cliente.telefono isEqual:[NSNull null]]   || cliente.telefono == nil   || [cliente.telefono isEqualToString:@""]   ||
       [cliente.citta isEqual:[NSNull null]]      || cliente.citta == nil      || [cliente.citta isEqualToString:@""]      ||
       [cliente.indirizzo isEqual:[NSNull null]]  || cliente.indirizzo == nil  || [cliente.indirizzo isEqualToString:@""]
       ){
        return false;
    }
    return true;
}

-(BOOL) checkIntervento:(InterventoCD *)inter{
    if([inter.motivo isEqual:[NSNull null]] || inter.motivo == nil  || [inter.motivo isEqualToString:@""] ||
       [inter.cliente isEqual:[NSNull null]]    || inter.cliente  == nil ||
       [inter.prodotto isEqual:[NSNull null]] || inter.prodotto == nil  || [inter.prodotto isEqualToString:@""] ||
       [inter.tecnico isEqual:[NSNull null]]    || inter.tecnico  == nil ||
       [inter.tipologia isEqual:[NSNull null]] || inter.tipologia == nil  || [inter.tipologia isEqualToString:@""] ||
       [inter.modalita isEqual:[NSNull null]] || inter.modalita == nil  || [inter.modalita isEqualToString:@""] ||
       [inter.dataora isEqual:[NSNull null]] || inter.dataora == nil
       ){
        
        return false;
    }
    return true;
}




-(NSNumber *)getMinDettagli{
    
    //Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
    
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    
	//istanziamo l'EntitÃ  da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription entityForName:@"DettaglioCD" inManagedObjectContext:context];
    
    
	//Settiamo la proprietÃ  Entity della Fetch Request
	[fetchRequest setEntity:entity];
    
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"iddettaglio"];
    NSExpression *minExpression     = [NSExpression expressionForFunction:@"min:"
                                                                arguments:[NSArray arrayWithObject:keyPathExpression]];
    
    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
    [expressionDescription setName:@"minID"];
    [expressionDescription setExpression:minExpression];
    [expressionDescription setExpressionResultType:NSInteger32AttributeType];
    
    [fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
    
    
    
    NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
    if(fo.count==0)return nil;
    
    
    NSNumber *min = ((DettaglioCD*)fo[0]).iddettaglio;
    if([min intValue]>0)return 0;
    else return min;
}












#pragma mark -
#pragma mark LOG


-(void) toLog:(NSString *) text{
    NSLog(@"%@",text);
    //[self.progressBar setProgress:[text floatValue]/1000.00];
}






#pragma mark -
#pragma mark Core Data stack


-(void) dropDatabase{
    NSLog(@"buttonReset Pressed");
    
    //Erase the persistent store from coordinator and also file manager.
    NSPersistentStore *store = [self.persistentStoreCoordinator.persistentStores lastObject];
    NSError *error = nil;
    NSURL *storeURL = store.URL;
    [self.persistentStoreCoordinator removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
    
    
    NSLog(@"Data Reset");
    
    //Make new persistent store for future saves   (Taken From Above Answer)
    if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Error %@", error);
    }
}


-(void) save{
    NSError *error;
    if (![[self managedObjectContext] save:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@, %@", error, [error userInfo],[error localizedDescription]);
        exit(-1);  // Fail
    }else{
        NSLog(@"Saving success!!!");
    }
}
-(void) refresh:(NSManagedObject*) obj{
    [[self managedObjectContext] refreshObject:obj mergeChanges:NO];
}

-(void) deleteObject:(NSManagedObject *) obj{
    [[self managedObjectContext] deleteObject:obj];
}


/**
 Returns the managed object context for the application.
 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
 */
- (NSManagedObjectContext *)managedObjectContext {
    //[self performSelectorInBackground:@selector(toLog:) withObject:@"managedObjectContext"];
    if (managedObjectContext_ != nil) {
        return managedObjectContext_;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext_ = [[NSManagedObjectContext alloc] init];
        [managedObjectContext_ setPersistentStoreCoordinator:coordinator];
    }
    return managedObjectContext_;
}


/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created from the application's model.
 */
- (NSManagedObjectModel *)managedObjectModel {
    
    if (managedObjectModel_ != nil) {
        return managedObjectModel_;
    }
    NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"InterventixDataModel" ofType:@"momd"];
    NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
    managedObjectModel_ = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return managedObjectModel_;
}


/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    //NSLog(@"persistentStoreCoordinator");
    if (persistentStoreCoordinator_ != nil) {
        return persistentStoreCoordinator_;
    }
    NSString *file =@"interventix.sqlite";
    /*if(self.id_user_logged != nil){
     file = [NSString stringWithFormat:@"ix_%d_%d.sqlite",[self.id_user_logged intValue],abs([[ComunicationsUtils getBaseUrl]hash])];
     }else{
     file = [NSString stringWithFormat:@"ix_nil_%d.sqlite",abs([[ComunicationsUtils getBaseUrl]hash])];
     }*/
    NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: file]];
    
    NSError *error = nil;
    persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    return persistentStoreCoordinator_;
}


#pragma mark -
#pragma mark Application's Documents directory

/**
 Returns the path to the application's Documents directory.
 */
- (NSString *)applicationDocumentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

@end